import json
import traceback

import requests
from flask import current_app
from flask import request, jsonify

from app import es
from apps.apis import api
from apps.core.auth import verify_token_str, verify_json_schema, verify_token_auth
# from apps.core.database import mongo
from apps.core.schemaall import query_by_ids_schema, query_onece_schema, token_schema, \
    es_lngid_schema, es_fileds_schema, query_onece_page_schema
from apps.logger.web_logger import weblog
from apps.models import SearchField, SubDb, SourceType
from apps.utils.request_utils import order_sql_logic, order_dsl_logic, update_dbcode
from apps.utils.return_info import ReturnInfo
from apps.utils.tools import ValueGetKey
from bson import ObjectId


@api.route("/search/fileds", methods=['POST'])
@verify_json_schema(es_fileds_schema)
@verify_token_auth(allowtokennull=True)
def es_fileds():
    """
    可查询字段
    高级查询的字段 兼容在该接口,以 advanced 区分， advanced = "true" 代表高级接口
    高级接口返回 200高级 模式的结构
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: es_fileds
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            advanced:
              type: string
              description: true or false 如果为false，接口返回一个list,如果为true,代表高级查询接口调用，返回一个object,且高级接口一定要token才行
              example: 'false'
    definitions:
      SearchField:
        type: object
        properties:
          index_field:
            type: string
            description: 在es中可查询的字段
            example: pub_year
          field_name:
            type: string
            description: 每个字段对应的名字
            example: 发布年
      ReturnInfoArray:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: array
            description: 所有条件的字段
            items:
              type: string
      ReturnInfoFileds:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: array
            description: 所有条件的字段
            items:
               $ref: '#/definitions/SearchField'
    consumes:
      - application/json
    produces:
      - application/json
    responses:
      200:
        description: 初级查询接口返回的格式.
        schema:
          $ref: '#/definitions/ReturnInfoArray'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":[{"field_name":"字段名","index_type":"后台索引类型"}]}
      200高级:
        description: 高级查询接口返回的格式.列表中放入字典，而不是直接用字典返回，主要是考虑到有序问题
        schema:
          $ref: '#/definitions/ReturnInfoFileds'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":[{"index_field":"author","field_name":"作者"},{"index_field":"journal_name","field_name":"期刊名"},{"index_field":"clc_no","field_name":"中图分类号"}]}
      FAILED:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
    :return:
    """
    ret_obj = ReturnInfo()

    jsons = request.json
    advanced = jsons.get("advanced")
    if advanced != "true":
        # token 不存在当游客处理
        token = jsons.get("token")
        if token != "":
            if not verify_token_str(token):
                ret_obj.msg_code = "FAILED"
                ret_obj.msg = "token 认证失败，有可能是过期"
                ret_obj.data = {"result": jsons}
                return jsonify(ret_obj.todict())

        searchFieldAll = SearchField.query.filter(SearchField.web_field_name != '').order_by(
            SearchField.web_serial.asc()).with_entities(SearchField.web_field_name,
                                                        SearchField.index_type).distinct().all()
        ret_obj.msg_code = "SUCCESS"
        ret_obj.msg = "返回es可查询的字段的字典"
        ret_obj.data = [{"field_name": searchField.web_field_name.strip(), "index_type": searchField.index_type} for
                        searchField
                        in
                        searchFieldAll]

        return jsonify(ret_obj.todict())
    else:
        token = jsons.get("token")
        if not verify_token_str(token):
            ret_obj.msg_code = "FAILED"
            ret_obj.msg = "token 认证失败，有可能是过期"
            ret_obj.data = {"result": jsons}
            return jsonify(ret_obj.todict())
        searchFieldAll = SearchField.query.order_by(
            SearchField.web_serial.asc()).all()
        ret_obj.msg_code = "SUCCESS"
        ret_obj.msg = "返回es可查询的字段的字典"
        ret_obj.data = [{"index_field": searchField.index_field.strip(), "field_name": searchField.field_name.strip(),
                         "index_type": searchField.index_type} for searchField in searchFieldAll]
        return jsonify(ret_obj.todict())


@api.route("/search/source_type", methods=['POST'])
@verify_json_schema(token_schema)
# @verify_token_auth(allowtokennull=True)
def es_source_type():
    """
    查询文献类型
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: es_source_type
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
    definitions:
      ReturnInfoSourceType:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: object
            description: 返回期刊类型
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        schema:
          $ref: '#/definitions/ReturnInfoSourceType'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":{"result": {"type_id_1":"type_name_1","type_id_2":"type_name_2"}}}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误

    :return:
    """
    ret_obj = ReturnInfo()
    SourceTypeAll = SourceType.query.filter_by(is_active=1).order_by(SourceType.web_serial.asc()).all()

    dicts = {}
    for sourcedType in SourceTypeAll:
        dicts[sourcedType.type_id] = sourcedType.type_name

    ret_obj.msg_code = "SUCCESS"
    ret_obj.msg = "返回es可查询的字段的字典"
    ret_obj.data = {"result": dicts}

    return jsonify(ret_obj.todict())


@api.route("/search/sub_db", methods=['POST'])
@verify_json_schema(token_schema)
@verify_token_auth(allowtokennull=True)
def es_sub_db():
    """
    可查询的所有子库
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: es_sub_db
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
    definitions:
      SubDB:
        type: object
        properties:
          sub_db_id:
            type: string
            description: 子库id,在es中查询时需要该字段的值
            example: 2
          sub_db_name:
            type: string
            description: 前端显示文字
            example: CNKI中国专利
      ReturnInfoSubDB:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: array
            description: 返回在es中可拆卸你的字段和前端显示的字典
            items:
              $ref: '#/definitions/SubDB'
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        schema:
          $ref: '#/definitions/ReturnInfoSubDB'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":{"result": {"subdb_id_1":"subdb_name_1","subdb_id_2":"subdb_name_2"}}}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误

    :return:
    """
    ret_obj = ReturnInfo()
    SubDbAll = SubDb.query.filter_by(is_active=1).all()

    ret_obj.msg_code = "SUCCESS"
    ret_obj.msg = "返回es可查询的字段的字典"
    dicts = {}
    for subdb in SubDbAll:
        dicts[subdb.sub_db_id] = subdb.sub_db_name
    ret_obj.data = {"result": dicts}
    return jsonify(ret_obj.todict())


# @api.route("/search/query", methods=['POST'])
# @verify_json_schema(es_query_schema)
# @verify_token_auth(allowtokennull=True)
def es_query():
    """
     查询 接口
     sql语句中逻辑运算符优先级，not > and > or
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: es
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            page:
              type: integer
              description: 页码，后台会自动减1再乘以size当作开始的位置
              example: 1
            size:
              type: integer
              description: 最大后台限制 1000条数据 默认 10
              example: 1000
            source_type:
              type: array
              description: 需要查询的字段,["*"] 代表着查询全部，目前使用查询全部这种模式
              example: ["2","3"]
              items:
                type: string
            sub_db_id:
              type: array
              description: 需要查询的子库,该字段必须是5位，不够前面补0,同时 ["*"] 代表全部字库
              example: ["00001","00002"]
              items:
                type: string
            pub_year_start:
              type: string
              description: 查询开始的年份,全部年用"*"
              example: '2000'
              example: '*'
            pub_year_end:
              type: string
              description: 查询结束的年份.
              example: '2017'
            where:
              type: array
              description: where 查询的条件.该条件的结果会与上面字库和年份and
              items:
                $ref: '#/definitions/Query'
    definitions:
      Query:
        type: object
        properties:
          link:
            type: string
            description: 连接符 and、or、not
            example: and
          feild_name:
            type: string
            description: 字段名
            example: 标题
          oparation:
            type: string
            description: equal、like
            example: like
          feild_value:
            type: string
            description:  前后两端模糊查询
            example: '长河坝'
      QueryResult:
        type: object
        properties:
          lngid:
            type: string
            description: 数据的主id，维普id
            example: 00002FCJKJ507JP16BDO5JP0M7R
          title:
            type: string
            description: 标题
            example: 长河坝水电站接触黏土调水工艺研究与应用

      ReturnInfoQuery:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: object
            description: 返回的信息全部在data中获取
            properties:
              es_total:
                type: integer
                description: 查询出来的总量
                example: 256
              query_total:
                type: integer
                description: 可查询数量，当小于10000 时传入 es_total 当大于10000时 10000
                example: 10000
              es_time:
                type: integer
                description: 执行查询的时间 ms
                example: 2134
              expression:
                type: string
                description: 显示的表达式
              querydata:
                type: array
                description: 数据组成的数组
                items:
                  $ref: '#/definitions/QueryResult'
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        schema:
          $ref: '#/definitions/ReturnInfoQuery'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":{"result":"这里放着es查询出来的结果","dsl":"这里返回生成的dsl，方便出现错误时调试"}}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误
    :return:
    """
    ret_obj = ReturnInfo()
    sql = ""
    jsons = request.json

    # 查询字段表
    searchFieldAll = SearchField.query.filter(SearchField.web_field_name != '').all()
    fieldsdicts = {searchField.index_field: searchField.web_field_name for searchField in searchFieldAll}
    # # 文献类型
    # sourceTypeAll = SourceType.query.all()
    # source_type_dicts = {sourceType.type_id: sourceType.type_name for sourceType in sourceTypeAll}

    # es的查询语句
    dsl = {}

    page = jsons.get("page")
    size = jsons.get("size")
    from_ = (int(page) - 1) * int(size)

    if from_ + size > 10000:
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "查询数据超过10000"
        ret_obj.data = ""
        return jsonify(ret_obj.todict())

    dsl["from"] = from_
    dsl["size"] = int(size)

    # 默认返回 lngid 和 title lngid 就是 _id 可以直接获取
    dsl["docvalue_fields"] = ["title"]

    # 查询的条件
    dsl["query"] = {"bool": {"must": []}}

    # 从哪些字库查询
    sub_db_id = jsons.get("sub_db_id")
    if sub_db_id != ["*"]:
        dsl["query"]["bool"]["must"].append({"terms": {"sub_db_id": list(sub_db_id)}})

    # 查询哪些类型
    source_type = jsons.get("source_type")
    if source_type != ["*"]:
        # source_type_list = ValueListGetKeyList(source_type_dicts, list(source_type))
        # dsl["query"]["bool"]["must"].append({"terms": {"source_type": source_type_list}})
        dsl["query"]["bool"]["must"].append({"terms": {"source_type": source_type}})
    # 年份开始时间
    startyear = jsons.get("pub_year_start")
    # 年份结束时间
    endyear = jsons.get("pub_year_end")
    if startyear != "*":
        dsl["query"]["bool"]["must"].append({"range": {"pub_year": {"gte": startyear, "lte": endyear}}})
    # 字段条件
    where = jsons.get("where")
    # operators = {"and": "must", "or": "should", "not": "must_not"}

    table = current_app.config.get("ES_INDEXS")
    wherestring = ""
    if where:
        # isbool, wherestring = order_sql(where, fieldsdicts)
        isbool, wherestring, wheresql = order_sql_logic(where, fieldsdicts)
        if not isbool:
            ret_obj.msg_code = "FAILED"
            ret_obj.msg = wherestring
            ret_obj.data = {"result": jsons}
            return jsonify(ret_obj.todict())

        # ES_MAPPING = current_app.config.get("ES_MAPPING")
        sql = "SELECT * from %s where %s" % (table, wheresql)
        query = {
            "query": sql
        }
        try:
            results = es.transport.perform_request('POST', '/_sql/translate', body=query)
            dicts = results["query"]
            dsl["query"]["bool"]["must"].append(dicts)
        except Exception as e:
            ret_obj.msg_code = "FAILED"
            ret_obj.msg = "sql 转 dsl 失败"
            ret_obj.data = {"result": "", "sql": sql, "errmsg": str(e)}
            return jsonify(ret_obj.todict())

    else:
        # where条件没有，其他条件全选着全库时
        if not dsl["query"]["bool"]["must"]:
            dsl["query"] = {"match_all": {}}
    result = ""
    # # 生成说明表达式
    # expression = sql_logic(where)
    try:
        result = es.search(index=current_app.config.get("ES_INDEXS"), body=dsl,
                           request_timeout=100)
        # params={'scroll': '1s'}
        total = result["hits"]["total"]["value"]
        es_time = result["took"]
        lists = []
        if total > 0:
            for items in result["hits"]["hits"]:
                lngid = items["_id"]
                title = items["_source"]["title"]
                lists.append({"lngid": lngid, "title": title})
        ret_obj.msg_code = "SUCCESS"
        ret_obj.msg = "成功"
        if total > 10000:
            query_total = 10000
        else:
            query_total = total
        resultdata = {"es_total": total, "es_time": es_time, "query_total": query_total, "querydata": lists}
        ret_obj.data = {"result": resultdata, "dsl": dsl, "sql": sql, "expression": wherestring}
    except Exception as e:
        print(traceback.format_exc())
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "执行查询失败"
        ret_obj.data = {"result": result, "dsl": dsl, "sql": sql, "expression": wherestring,
                        "errmsg": traceback.format_exc()}
    return jsonify(ret_obj.todict())


def es_query_onece_old():
    """
     查询lngid 当大于1000时 一次返回1000条,本接口返回id和title
     sql语句中逻辑运算符优先级，not > and > or
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: queryonce
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            source_type:
              type: array
              description: 需要查询的字段,["*"] 代表着查询全部，目前使用查询全部这种模式
              example: ["2","3"]
              items:
                type: string
            sub_db_id:
              type: array
              description: 需要查询的子库,该字段必须是5位，不够前面补0,同时 ["*"] 代表全部字库
              example: ["00001","00002"]
              items:
                type: string
            pub_year_start:
              type: string
              description: 查询开始的年份,全部年用"*"
              example: '2000'
              example: '*'
            pub_year_end:
              type: string
              description: 查询结束的年份.
              example: '2017'
            where:
              type: array
              description: where 查询的条件.该条件的结果会与上面字库和年份and
              items:
                $ref: '#/definitions/Query'
    definitions:
      Query:
        type: object
        properties:
          link:
            type: string
            description: 连接符 and、or、not
            example: and
          feild_name:
            type: string
            description: 字段名
            example: 标题
          oparation:
            type: string
            description: equal、like
            example: like
          feild_value:
            type: string
            description:  前后两端模糊查询
            example: '长河坝'
      QueryResult:
        type: object
        properties:
          lngid:
            type: string
            description: 数据的主id，维普id
            example: 00002FCJKJ507JP16BDO5JP0M7R
          title:
            type: string
            description: 标题
            example: 长河坝水电站接触黏土调水工艺研究与应用

      ReturnInfoQuery:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: object
            description: 返回的信息全部在data中获取
            properties:
              es_total:
                type: integer
                description: 查询出来的总量
                example: 256
              es_time:
                type: integer
                description: 执行查询的时间 ms
                example: 2134
              expression:
                type: string
                description: 显示的表达式
              querydata:
                type: array
                description: 数据组成的数组
                items:
                  $ref: '#/definitions/QueryResult'
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        schema:
          $ref: '#/definitions/ReturnInfoQuery'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":{"result":"这里放着es查询出来的结果","dsl":"这里返回生成的dsl，方便出现错误时调试"}}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误
    :return:
    """
    ret_obj = ReturnInfo()
    sql = ""
    jsons = request.json
    table = current_app.config.get("ES_INDEXS")

    # 查询字段表
    searchFieldAll = SearchField.query.filter(SearchField.web_field_name != '').all()
    fieldsdicts = {searchField.index_field: searchField.web_field_name for searchField in searchFieldAll}
    # # 文献类型
    # sourceTypeAll = SourceType.query.all()
    # source_type_dicts = {sourceType.type_id: sourceType.type_name for sourceType in sourceTypeAll}

    # es的查询语句
    dsl = {}
    dsl["size"] = 1000
    # 默认返回 lngid 和 title
    dsl["docvalue_fields"] = ["title"]

    # 查询的条件
    dsl["query"] = {"bool": {"must": []}}

    # 从哪些字库查询
    sub_db_id = jsons.get("sub_db_id")
    if sub_db_id != ["*"]:
        dsl["query"]["bool"]["must"].append({"terms": {"sub_db_id": list(sub_db_id)}})

    source_type = jsons.get("source_type")
    if source_type != ["*"]:
        # source_type_list = ValueListGetKeyList(source_type_dicts, list(source_type))
        # dsl["query"]["bool"]["must"].append({"terms": {"source_type": source_type_list}})
        dsl["query"]["bool"]["must"].append({"terms": {"source_type": source_type}})
    # 年份开始时间
    startyear = jsons.get("pub_year_start")
    # 年份结束时间
    endyear = jsons.get("pub_year_end")
    if startyear != "*":
        dsl["query"]["bool"]["must"].append({"range": {"pub_year": {"gte": startyear, "lte": endyear}}})
    # 字段条件
    where = jsons.get("where")
    # operators = {"and": "must", "or": "should", "not": "must_not"}
    wherestring = ""
    if where:
        # isbool, wherestring = order_sql(where, fieldsdicts)
        isbool, wherestring, wheresql = order_sql_logic(where, fieldsdicts)
        if not isbool:
            ret_obj.msg_code = "FAILED"
            ret_obj.msg = wherestring
            ret_obj.data = {"result": jsons}
            return jsonify(ret_obj.todict())
        # ES_MAPPING = current_app.config.get("ES_MAPPING")
        sql = "SELECT * from %s where %s" % (table, wheresql)
        query = {
            "query": sql
        }
        try:
            results = es.transport.perform_request('POST', '/_sql/translate', body=query)
            dicts = results["query"]
            dsl["query"]["bool"]["must"].append(dicts)
        except Exception as e:
            ret_obj.msg_code = "FAILED"
            ret_obj.msg = "sql 转 dsl 失败"
            ret_obj.data = {"result": "", "sql": sql, "errmsg": str(e)}
            return jsonify(ret_obj.todict())
    else:
        # where条件没有，其他条件全选着全库时
        if not dsl["query"]["bool"]["must"]:
            dsl["query"] = {"match_all": {}}
    result = ""
    # # 生成说明表达式
    # expression = sql_logic(where)
    try:
        result = es.search(index=current_app.config.get("ES_INDEXS"), params={'scroll': '1s'}, body=dsl,
                           request_timeout=100)
        total = result["hits"]["total"]["value"]
        es_time = result["took"]
        lists = []
        if total > 0:
            for items in result["hits"]["hits"]:
                lngid = items["_id"]
                title = items["fields"]["title"][0]
                lists.append({"lngid": lngid, "title": title})
        ret_obj.msg_code = "SUCCESS"
        ret_obj.msg = "成功"
        resultdata = {"es_total": total, "es_time": es_time, "querydata": lists}
        ret_obj.data = {"result": resultdata, "dsl": dsl, "sql": sql, "expression": wherestring}
    except Exception as e:
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "执行查询失败"
        ret_obj.data = {"result": result, "dsl": dsl, "sql": sql, "expression": wherestring, "errmsg": str(e)}
    return jsonify(ret_obj.todict())


def es_query_onece_old_1():
    """
     查询lngid 当大于10000时 一次返回10000条,本接口只返回id
     sql语句中逻辑运算符优先级，not > and > or
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: queryonce
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            source_type:
              type: array
              description: 需要查询的字段,["*"] 代表着查询全部，目前使用查询全部这种模式
              example: ["2","3"]
              items:
                type: string
            sub_db_id:
              type: array
              description: 需要查询的子库,该字段必须是5位，不够前面补0,同时 ["*"] 代表全部字库
              example: ["00001","00002"]
              items:
                type: string
            pub_year_start:
              type: string
              description: 查询开始的年份,全部年用"*"
              example: '2000'
              example: '*'
            pub_year_end:
              type: string
              description: 查询结束的年份.
              example: '2017'
            where:
              type: array
              description: where 查询的条件.该条件的结果会与上面字库和年份and
              items:
                $ref: '#/definitions/Query'
    definitions:
      Query:
        type: object
        properties:
          link:
            type: string
            description: 连接符 and、or、not
            example: and
          feild_name:
            type: string
            description: 字段名
            example: 标题
          oparation:
            type: string
            description: equal、like
            example: like
          feild_value:
            type: string
            description:  前后两端模糊查询
            example: '长河坝'
      ReturnInfoQuery:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: object
            description: 返回的信息全部在data中获取
            properties:
              es_total:
                type: integer
                description: 查询出来的总量
                example: 256
              es_time:
                type: integer
                description: 执行查询的时间 ms
                example: 2134
              expression:
                type: string
                description: 显示的表达式
              querydata:
                type: array
                description: 数据组成的数组
                items:
                  type: string
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        schema:
          $ref: '#/definitions/ReturnInfoQuery'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":{"result":"这里放着es查询出来的结果","dsl":"这里返回生成的dsl，方便出现错误时调试"}}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误
    :return:
    """
    ret_obj = ReturnInfo()
    sql = ""
    jsons = request.json

    # 查询字段表
    searchFieldAll = SearchField.query.filter(SearchField.web_field_name != '').all()
    fieldsdicts = {searchField.index_field: searchField.web_field_name for searchField in searchFieldAll}
    # 文献类型
    # sourceTypeAll = SourceType.query.all()
    # source_type_dicts = {sourceType.type_id: sourceType.type_name for sourceType in sourceTypeAll}

    # es的查询语句
    dsl = {}
    dsl["size"] = 10000
    # 默认返回 lngid 和 title
    # dsl["docvalue_fields"] = ["title"]

    # 查询的条件
    dsl["query"] = {"bool": {"must": []}}

    # 从哪些字库查询
    sub_db_id = jsons.get("sub_db_id")
    if sub_db_id != ["*"]:
        dsl["query"]["bool"]["must"].append({"terms": {"sub_db_id": list(sub_db_id)}})

    source_type = jsons.get("source_type")
    if source_type != ["*"]:
        # source_type_list = ValueListGetKeyList(source_type_dicts, list(source_type))
        # dsl["query"]["bool"]["must"].append({"terms": {"source_type": source_type_list}})
        dsl["query"]["bool"]["must"].append({"terms": {"source_type": source_type}})
    # 年份开始时间
    startyear = jsons.get("pub_year_start")
    # 年份结束时间
    endyear = jsons.get("pub_year_end")
    if startyear != "*":
        dsl["query"]["bool"]["must"].append({"range": {"pub_year": {"gte": startyear, "lte": endyear}}})
    # 字段条件
    where = jsons.get("where")
    # operators = {"and": "must", "or": "should", "not": "must_not"}

    table = current_app.config.get("ES_INDEXS")
    if where:
        # isbool, wherestring = order_sql(where, fieldsdicts)
        isbool, wherestring, wheresql = order_sql_logic(where, fieldsdicts)
        if not isbool:
            ret_obj.msg_code = "FAILED"
            ret_obj.msg = wherestring
            ret_obj.data = {"result": jsons}
            return jsonify(ret_obj.todict())

        sql = "SELECT * from %s where %s" % (table, wheresql)
        query = {
            "query": sql
        }
        try:
            results = es.transport.perform_request('POST', '/_sql/translate', body=query)
            dicts = results["query"]
            dsl["query"]["bool"]["must"].append(dicts)
        except Exception as e:
            ret_obj.msg_code = "FAILED"
            ret_obj.msg = "sql 转 dsl 失败"
            ret_obj.data = {"result": "", "sql": sql, "errmsg": str(e)}
            return jsonify(ret_obj.todict())
    else:
        # where条件没有，其他条件全选着全库时
        if not dsl["query"]["bool"]["must"]:
            dsl["query"] = {"match_all": {}}
    result = ""
    # # 生成说明表达式
    # expression = sql_logic(where)
    try:
        result = es.search(index=current_app.config.get("ES_INDEXS"), params={'scroll': '1s'}, body=dsl,
                           request_timeout=100)
        total = result["hits"]["total"]["value"]
        es_time = result["took"]
        lists = []
        if total > 0:
            for items in result["hits"]["hits"]:
                lngid = items["_id"]
                lists.append(lngid)
        ret_obj.msg_code = "SUCCESS"
        ret_obj.msg = "成功"
        resultdata = {"es_total": total, "es_time": es_time, "querydata": lists}
        ret_obj.data = {"result": resultdata, "dsl": dsl, "sql": sql, "expression": wherestring}
    except Exception as e:
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "执行查询失败"
        ret_obj.data = {"result": result, "dsl": dsl, "sql": sql, "expression": wherestring, "errmsg": str(e)}
    return jsonify(ret_obj.todict())


@api.route("/search/query_once", methods=['POST'])
@verify_json_schema(query_onece_schema)
# @verify_token_auth(allowtokennull=True)
def es_query_onece():
    """
     查询lngid 当大于10000时 一次返回10000条,本接口只返回id
     sql语句中逻辑运算符优先级，not > and > or
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: queryonce
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            source_type:
              type: array
              description: 需要查询的字段,["*"] 代表着查询全部，目前使用查询全部这种模式
              example: ["2","3"]
              items:
                type: string
            sub_db_id:
              type: array
              description: 需要查询的子库,该字段必须是5位，不够前面补0,同时 ["*"] 代表全部字库
              example: ["00001","00002"]
              items:
                type: string
            pub_year_start:
              type: string
              description: 查询开始的年份,全部年用"*"
              example: '2000'
              example: '*'
            pub_year_end:
              type: string
              description: 查询结束的年份.
              example: '2017'
            where:
              type: array
              description: where 查询的条件.该条件的结果会与上面字库和年份and
              items:
                $ref: '#/definitions/Query'
    definitions:
      Query:
        type: object
        properties:
          link:
            type: string
            description: 连接符 and、or、not
            example: and
          feild_name:
            type: string
            description: 字段名
            example: 标题
          oparation:
            type: string
            description: equal、like
            example: like
          feild_value:
            type: string
            description:  前后两端模糊查询
            example: '长河坝'
      QueryData:
        type: object
        properties:
          lngid:
            type: string
            description: 数据的主id
            example: 00002G4K498O7JP169DO5JPXMJR
          index:
            type: integer
            description: 数字，与dbcode映射得到数据库名
            example: 1
      ReturnInfoQuery:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: object
            description: 返回的信息全部在data中获取
            properties:
              result:
                type: object
                description: 返回的信息全部在data中获取
                properties:
                  es_total:
                    type: integer
                    description: 查询出来的总量
                    example: 256
                  es_time:
                    type: integer
                    description: 执行查询的时间 ms
                    example: 2134
                  expression:
                    type: string
                    description: 显示的表达式
                  querydata:
                    type: array
                    description: 数据组成的数组
                    items:
                      $ref: '#/definitions/QueryData'
              dsl:
                type: object
                description: dsl 的查询语句
              expression:
                type: string
                description: 表达式的文字说明
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        schema:
          $ref: '#/definitions/ReturnInfoQuery'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":{"result":"这里放着es查询出来的结果","dsl":"这里返回生成的dsl，方便出现错误时调试"}}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误
    :return:
    """
    ret_obj = ReturnInfo()
    jsons = request.json
    table = current_app.config.get("ES_INDEXS")
    dbcode = current_app.config.get("ES_DBCODE")

    # index_source_type = {}
    # 每个source_type类型对应一个index时需要
    # for key in dbcode.keys():
    #     print(key)
    #     index_source_type[key] = key.split("_")[5]

    # 查询字段表
    searchFieldAll = SearchField.query.filter(SearchField.web_field_name != '').all()
    # fieldsdicts = {searchField.index_field: searchField.web_field_name for searchField in searchFieldAll}
    fieldsdicts = {}
    filedstypedicts = {}
    for searchField in searchFieldAll:
        fieldsdicts[searchField.index_field.strip()] = searchField.web_field_name.strip()
        filedstypedicts[searchField.index_field.strip()] = searchField.index_type

    # 文献类型
    # sourceTypeAll = SourceType.query.all()
    # source_type_dicts = {sourceType.type_id: sourceType.type_name for sourceType in sourceTypeAll}

    # es的查询语句
    dsl = {}
    dsl["size"] = 10000
    # 查询的条件
    dsl["_source"] = ["keyid", "lngid", "title", "author", "pub_year", "source_type"]
    dsl["query"] = {"bool": {"must": []}}
    # 从哪些字库查询
    sub_db_id = jsons.get("sub_db_id")
    if sub_db_id != ["*"]:
        dsl["query"]["bool"]["must"].append({"terms": {"sub_db_id": list(sub_db_id)}})
    else:
        SubDbAll = SubDb.query.filter_by(is_active=1).all()
        sub_db_id_list = []
        for subdb in SubDbAll:
            sub_db_id_list.append(subdb.sub_db_id)
        dsl["query"]["bool"]["must"].append({"terms": {"sub_db_id": sub_db_id_list}})

    source_type = jsons.get("source_type")
    if source_type != ["*"]:
        # source_type_list = ValueListGetKeyList(source_type_dicts, list(source_type))
        # dsl["query"]["bool"]["must"].append({"terms": {"source_type": source_type_list}})
        dsl["query"]["bool"]["must"].append({"terms": {"source_type": source_type}})
        # index_list = []
        # for key in source_type:
        #     index_list.extend(list(ValueGetKey(index_source_type, key)))
        # if not index_list:
        #     alias = '/_alias/{}'.format(table)
        #     results = es.transport.perform_request('GET', alias)
        #     i = 0
        #     dbcode = {}
        #     for key in results.keys():
        #         i = i + 1
        #         dbcode[key] = i
        #     weblog.info("dbcode的更新字典为 %s" % dbcode)
        #     current_app.config['ES_DBCODE'] = dbcode
        #     ret_obj.msg_code = "FAILED"
        #     ret_obj.msg = "没有对应文献类型的资源"
        #     ret_obj.data = {"result": jsons}
        #     return jsonify(ret_obj.todict())
        # else:
        #     index = ','.join(index_list)
    # else:
    #     index = table
    index = table
    weblog.info("查询的index为{}".format(index))
    # 年份开始时间
    startyear = jsons.get("pub_year_start")
    # 年份结束时间
    endyear = jsons.get("pub_year_end")
    if startyear != "*":
        dsl["query"]["bool"]["must"].append({"range": {"pub_year": {"gte": startyear, "lte": endyear}}})
    # 字段条件
    where = jsons.get("where")
    wherestring = ""
    if where:
        _dsl, wherestring = order_dsl_logic(where, fieldsdicts, filedstypedicts)
        if not dsl["query"]["bool"]["must"]:
            dsl["query"] = _dsl
        else:
            try:
                if _dsl["bool"]["must"]:
                    # 两个列表合成一个
                    dsl["query"]["bool"]["must"].extend(_dsl["bool"]["must"])
                else:
                    dsl["query"]["bool"]["must"].append(_dsl)
            except:
                dsl["query"]["bool"]["must"].append(_dsl)
    result = ""
    try:
        result = es.search(index=index, params={'scroll': '1s'}, body=dsl,
                           request_timeout=100)
        total = result["hits"]["total"]["value"]
        es_time = result["took"]
        lists = []
        if total > 0:
            for items in result["hits"]["hits"]:
                # lngid = items["_id"]
                # index = items["_source"]["source_type"]
                # lists.append({"lngid": lngid, "index": index})
                lists.append(items["_source"])
        ret_obj.msg_code = "SUCCESS"
        ret_obj.msg = "成功"
        resultdata = {"es_total": total, "es_time": es_time, "querydata": lists}
        ret_obj.data = {"result": resultdata, "dsl": dsl, "expression": wherestring}
    except Exception as e:
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "执行查询失败"
        ret_obj.data = {"result": result, "dsl": dsl, "expression": wherestring, "errmsg": traceback.format_exc()}
    return jsonify(ret_obj.todict())


@api.route("/search/query_once_page", methods=['POST'])
@verify_json_schema(query_onece_page_schema)
# @verify_token_auth(allowtokennull=True)
def es_query_page_onece():
    """
     查询lngid 当大于10000时 一次返回10000条,本接口只返回id
     sql语句中逻辑运算符优先级，not > and > or
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: queryoncepage
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            source_type:
              type: array
              description: 需要查询的字段,["*"] 代表着查询全部，目前使用查询全部这种模式
              example: ["2","3"]
              items:
                type: string
            sub_db_id:
              type: array
              description: 需要查询的子库,该字段必须是5位，不够前面补0,同时 ["*"] 代表全部字库
              example: ["00001","00002"]
              items:
                type: string
            pub_year_start:
              type: string
              description: 查询开始的年份,全部年用"*"
              example: '2000'
              example: '*'
            pub_year_end:
              type: string
              description: 查询结束的年份.
              example: '2017'
            page:
              type: integer
              description: 页码.
              example: 1
            size:
              type: integer
              description: 每页的数量
              example: 20
            where:
              type: array
              description: where 查询的条件.该条件的结果会与上面字库和年份and
              items:
                $ref: '#/definitions/Query'
    definitions:
      Query:
        type: object
        properties:
          link:
            type: string
            description: 连接符 and、or、not
            example: and
          feild_name:
            type: string
            description: 字段名
            example: 标题
          oparation:
            type: string
            description: equal、like
            example: like
          feild_value:
            type: string
            description:  前后两端模糊查询
            example: '长河坝'
      QueryData:
        type: object
        properties:
          lngid:
            type: string
            description: 数据的主id
            example: 00002G4K498O7JP169DO5JPXMJR
          index:
            type: integer
            description: 数字，与dbcode映射得到数据库名
            example: 1
      ReturnInfoQuery:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: object
            description: 返回的信息全部在data中获取
            properties:
              result:
                type: object
                description: 返回的信息全部在data中获取
                properties:
                  es_total:
                    type: integer
                    description: 查询出来的总量
                    example: 256
                  es_time:
                    type: integer
                    description: 执行查询的时间 ms
                    example: 2134
                  expression:
                    type: string
                    description: 显示的表达式
                  querydata:
                    type: array
                    description: 数据组成的数组
                    items:
                      $ref: '#/definitions/QueryData'
              dsl:
                type: object
                description: dsl 的查询语句
              expression:
                type: string
                description: 表达式的文字说明
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        schema:
          $ref: '#/definitions/ReturnInfoQuery'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":{"result":"这里放着es查询出来的结果","dsl":"这里返回生成的dsl，方便出现错误时调试"}}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误
    :return:
    """
    ret_obj = ReturnInfo()
    jsons = request.json
    table = current_app.config.get("ES_INDEXS")
    dbcode = current_app.config.get("ES_DBCODE")

    # index_source_type = {}
    # 每个source_type类型对应一个index时需要
    # for key in dbcode.keys():
    #     print(key)
    #     index_source_type[key] = key.split("_")[5]

    # 查询字段表
    searchFieldAll = SearchField.query.filter(SearchField.web_field_name != '').all()
    # fieldsdicts = {searchField.index_field: searchField.web_field_name for searchField in searchFieldAll}
    fieldsdicts = {}
    filedstypedicts = {}
    for searchField in searchFieldAll:
        fieldsdicts[searchField.index_field.strip()] = searchField.web_field_name.strip()
        filedstypedicts[searchField.index_field.strip()] = searchField.index_type

    # 文献类型
    # sourceTypeAll = SourceType.query.all()
    # source_type_dicts = {sourceType.type_id: sourceType.type_name for sourceType in sourceTypeAll}

    # es的查询语句
    dsl = {}
    page = jsons.get("page")
    size = jsons.get("size")
    if page * size > 10000:
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "查询数据超过10000"
        ret_obj.data = "page:{},size:{}".format(str(page), str(size))
        return jsonify(ret_obj.todict())

    from_ = (page - 1) * size
    dsl["from"] = from_
    dsl["size"] = size
    # 查询的条件
    dsl["_source"] = ["keyid", "lngid", "title", "author", "pub_year", "source_type"]
    dsl["query"] = {"bool": {"must": []}}
    # 从哪些字库查询
    sub_db_id = jsons.get("sub_db_id")
    if sub_db_id != ["*"]:
        dsl["query"]["bool"]["must"].append({"terms": {"sub_db_id": list(sub_db_id)}})
    else:
        SubDbAll = SubDb.query.filter_by(is_active=1).all()
        sub_db_id_list = []
        for subdb in SubDbAll:
            sub_db_id_list.append(subdb.sub_db_id)
        dsl["query"]["bool"]["must"].append({"terms": {"sub_db_id": sub_db_id_list}})

    source_type = jsons.get("source_type")
    if source_type != ["*"]:
        # source_type_list = ValueListGetKeyList(source_type_dicts, list(source_type))
        # dsl["query"]["bool"]["must"].append({"terms": {"source_type": source_type_list}})
        dsl["query"]["bool"]["must"].append({"terms": {"source_type": source_type}})
        # index_list = []
        # for key in source_type:
        #     index_list.extend(list(ValueGetKey(index_source_type, key)))
        # if not index_list:
        #     alias = '/_alias/{}'.format(table)
        #     results = es.transport.perform_request('GET', alias)
        #     i = 0
        #     dbcode = {}
        #     for key in results.keys():
        #         i = i + 1
        #         dbcode[key] = i
        #     weblog.info("dbcode的更新字典为 %s" % dbcode)
        #     current_app.config['ES_DBCODE'] = dbcode
        #     ret_obj.msg_code = "FAILED"
        #     ret_obj.msg = "没有对应文献类型的资源"
        #     ret_obj.data = {"result": jsons}
        #     return jsonify(ret_obj.todict())
        # else:
        #     index = ','.join(index_list)
    # else:
    #     index = table
    index = table
    weblog.info("查询的index为{}".format(index))
    # 年份开始时间
    startyear = jsons.get("pub_year_start")
    # 年份结束时间
    endyear = jsons.get("pub_year_end")
    if startyear != "*":
        dsl["query"]["bool"]["must"].append({"range": {"pub_year": {"gte": startyear, "lte": endyear}}})
    # 字段条件
    where = jsons.get("where")
    wherestring = ""
    if where:
        _dsl, wherestring = order_dsl_logic(where, fieldsdicts, filedstypedicts)
        if not dsl["query"]["bool"]["must"]:
            dsl["query"] = _dsl
        else:
            try:
                if _dsl["bool"]["must"]:
                    # 两个列表合成一个
                    dsl["query"]["bool"]["must"].extend(_dsl["bool"]["must"])
                else:
                    dsl["query"]["bool"]["must"].append(_dsl)
            except:
                dsl["query"]["bool"]["must"].append(_dsl)
    result = ""
    try:
        # params={'scroll': '1s'},
        # from启动滚动时，不能再在搜索请求正文中使用该参数。在这些情况下，该参数已被忽略，现在还会引发错误。
        # 20220309
        result = es.search(index=index, body=dsl,
                           request_timeout=100)
        total = result["hits"]["total"]["value"]
        es_time = result["took"]
        lists = []
        if total > 0:
            for items in result["hits"]["hits"]:
                # lngid = items["_id"]
                # index = items["_source"]["source_type"]
                # lists.append({"lngid": lngid, "index": index})
                lists.append(items["_source"])
        ret_obj.msg_code = "SUCCESS"
        ret_obj.msg = "成功"
        resultdata = {"es_total": total, "es_time": es_time, "querydata": lists}
        ret_obj.data = {"result": resultdata, "dsl": dsl, "expression": wherestring}
    except Exception as e:
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "执行查询失败"
        ret_obj.data = {"result": result, "dsl": dsl, "expression": wherestring, "errmsg": traceback.format_exc()}
    return jsonify(ret_obj.todict())


def es_lngid():
    """
    按照lngid 查询某条记录的详细信息
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: eslngid
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            lngid:
              type: string
              description: lngid 维普唯一id
              example: 00002G4K498O7JP169DO5JPXMJR
            index:
              type: integer
              description: 数据库对应的数字
              example: 1
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":{"result":"这里放着es查询出来的结果"}}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误
    :return:
    """
    ret_obj = ReturnInfo()
    jsons = request.json
    dbcode = current_app.config.get("ES_DBCODE")
    index = jsons.get("index")
    lngid = jsons.get("lngid")

    results = ValueGetKey(dbcode, index)
    if results:
        index = results.pop()
    else:
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "dbcode 中没有对应的index"
        ret_obj.data = {"result": jsons}
        return jsonify(ret_obj.todict())

    try:
        results = es.get(index=index, id=lngid, params={'stored_fields': 'full_field'})
        if results["found"]:
            resultstring = results["fields"]["full_field"][0]
            result = json.loads(resultstring)
            ret_obj.msg_code = "SUCCESS"
            ret_obj.msg = "成功"
            ret_obj.data = {"result": result}
        else:
            ret_obj.msg_code = "FAILED"
            ret_obj.msg = "没有lngid对应的值"
            ret_obj.data = {"result": jsons}
    except Exception as e:
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "查询es 出错"
        ret_obj.data = {"result": jsons, "errmsg": str(e)}
    return jsonify(ret_obj.todict())


@api.route("/search/keyid", methods=['POST'])
@verify_json_schema(es_lngid_schema)
@verify_token_auth(allowtokennull=True)
def es_lngid_mongodb():
    """
    按照lngid 查询某条记录的详细信息
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: eslngid
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            keyid:
              type: string
              description: keyid 维普唯一id
              example: 00002G4K498O7JP169DO5JPXMJR
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":{"result":"这里放着查询出来的结果"}}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误
    :return:
    """
    ret_obj = ReturnInfo()
    jsons = request.json
    keyid = jsons.get("keyid")
    # 废弃
    # index = jsons.get("index")
    row = ""
    try:
        # base_obj_meta_a = "base_obj_meta_a_" + str(index)
        base_obj_meta_a = "base_obj_meta_a"
        # row_mate = mongo.db[base_obj_meta_a].find_one({"_id": keyid})
        url = "http://192.168.31.165:19001/datawarehouse/query/title/" + keyid
        response = requests.get(url)
        # 检查响应状态码
        if response.status_code == 200:
            data_tp = response.json()
            if "totleCount" in data_tp.keys() and data_tp["totleCount"] == 0:
                row_mate = {}
            else:
                # 解析响应内容为 JSON
                row_mate = data_tp["data"]
        else:
            raise Exception(f"请求高可用失败，状态码: {response.status_code},url:{url}")

        ret_obj.msg_code = "SUCCESS"
        ret_obj.msg = "成功"
        ret_obj.data = {"result": row_mate}
        return jsonify(ret_obj.todict())
    except Exception as e:
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "失败,可能是查询错误，或者查询的结果本生包含错误信息"
        ret_obj.data = {"result": row, "errmsg": str(e)}
        return jsonify(ret_obj.todict())


@api.route("/search/ref_keyid", methods=['POST'])
@verify_json_schema(es_lngid_schema)
@verify_token_auth(allowtokennull=True)
def es_lngid_ref_mongodb():
    """
    按照lngid 查询某条记录的详细信息
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: eslngid
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            keyid:
              type: string
              description: lngid 维普唯一id
              example: 00002G4K498O7JP169DO5JPXMJR
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":{"result":"这里放着es查询出来的结果"}}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误
    :return:
    """
    ret_obj = ReturnInfo()
    jsons = request.json
    keyid = jsons.get("keyid")
    row = ""
    try:
        url = "http://192.168.31.165:19001/datawarehouse/query/refer/" + keyid
        # row = mongo.db.base_obj_ref_a.find_one({"_id": keyid})
        response = requests.get(url)
        # 检查响应状态码
        if response.status_code == 200:
            data_tp = response.json()
            if "totleCount" in data_tp.keys() and data_tp["totleCount"] == 0:
                row = {"refer_info": []}
            else:
                # 解析响应内容为 JSON
                row = data_tp["data"]
        else:
            raise Exception(f"请求高可用失败，状态码: {response.status_code},url:{url}")

        if row:
            list_ref = row["refer_info"]
        else:
            list_ref = []
        ret_obj.msg_code = "SUCCESS"
        ret_obj.msg = "成功"
        ret_obj.data = {"result": list_ref}
        return jsonify(ret_obj.todict())
    except Exception as e:
        traceback.print_exc()
        ret_obj.msg_code = "FAILED"
        ret_obj.msg = "失败,可能是查询错误，或者查询的结果本生包含错误信息"
        ret_obj.data = {"result": row, "errmsg": str(e)}
        return jsonify(ret_obj.todict())


def es_query_by_ids():
    """
    通过id列表查询title
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: querybyids
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            ids:
              type: array
              description: id的字典数组
              items:
                $ref: '#/definitions/QueryData'
    definitions:
      QueryData:
        type: object
        properties:
          lngid:
            type: string
            description: 数据的主id
            example: 00002G4K498O7JP169DO5JPXMJR
          index:
            type: integer
            description: 数字，与dbcode映射得到数据库名
            example: 1
      ReturnInfoQuery:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: array
            description: 返回的信息全部在data中获取
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        schema:
          $ref: '#/definitions/ReturnInfoQuery'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":[{"这里放着es查询出来的结果"},{}]}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误
    :return:
    """
    list_original = []
    ret_obj = ReturnInfo()
    jsons = request.json
    ids = jsons.get("ids")
    dbcode = current_app.config.get("ES_DBCODE")
    dicts = {}
    for items in ids:
        index = items["index"]
        lngid = items["lngid"]
        list_original.append(lngid)
        if index in list(dicts.keys()):
            dicts[index].append(lngid)
        else:
            dicts[index] = [lngid]
    lists = []
    result_dicts = {}
    for value in list(dicts.keys()):
        ids = dicts[value]
        body = {
            "ids": ids
        }
        index = ValueGetKey(dbcode, value)
        index = index.pop()
        result = ""
        try:
            result = es.mget(body, index=index, doc_type='_doc',
                             params={"stored_fields": "full_field"})
            for items in result["docs"]:
                resultstring = items["fields"]["full_field"][0]
                result_temp = json.loads(resultstring)
                result_dicts[result_temp["lngid"]] = result_temp
        except Exception as e:
            ret_obj.msg_code = "FAILED"
            ret_obj.msg = "失败,可能是查询错误，或者查询的结果本生包含错误信息"
            ret_obj.data = {"result": result, "errmsg": str(e)}
            return jsonify(ret_obj.todict())
    for lngid in list_original:
        lists.append(result_dicts[lngid])
    ret_obj.msg_code = "SUCCESS"
    ret_obj.msg = "成功"
    ret_obj.data = lists
    return jsonify(ret_obj.todict())


@api.route("/search/query_by_ids", methods=['POST'])
@verify_json_schema(query_by_ids_schema)
@verify_token_auth(allowtokennull=True)
def es_query_by_ids_mongodb():
    """
    通过id列表查询title
    ---
    tags:
      - search
    parameters:
      - in: body
        name: body
        required: true
        description: JSON 参数.
        schema:
          id: querybyids
          properties:
            token:
              type: string
              description: 用户认证. 为空被当作游客,将不认证 空为 "" (空字符串)
              example: eyJhbGciOiJIUzUxMiIsImlhdCI6MTU3Mjg0NzY3OSwiZXhwIjoxNTcyODQ4Mjc5fQ.eyJpZCI6MX0.rLbJ_6UQHuHoEA2xjbqtUa28Ogtf2I4JEDa0En0WjgB5pe5L1gT6F5L0RktZuJBE1lBEGT0TAJ1YC7PddwE-Cg
            ids:
              type: array
              description: id的字典数组
              items:
                $ref: '#/definitions/QueryData'
    definitions:
      QueryData:
        type: object
        properties:
          lngid:
            type: string
            description: 数据的主id
            example: 00002G4K498O7JP169DO5JPXMJR
          index:
            type: integer
            description: 数字，与dbcode映射得到数据库名
            example: 1
      ReturnInfoQuery:
        type: object
        properties:
          msg_code:
            type: string
            description: SUCCESS 或者 FAILED.
            example: SUCCESS
          msg:
            type: string
            description: 说明文字，帮助找到失败原因
            example: 不能使用get请求
          data:
            type: array
            description: 返回的信息全部在data中获取
    consumes:
      - application/json
    produces:
      - application/json

    responses:
      200:
        description: OK.
        schema:
          $ref: '#/definitions/ReturnInfoQuery'
        examples:
          returninfo: {"msg_code":"SUCCESS","msg":"成功","data":[{"这里放着es查询出来的结果"},{}]}
      400:
        description: 上传数据有不符合规则,data中放入的是上传的数据.
        examples:
          returninfo: {"msg_code":"FAILED","msg":"上传格式错误","data":{"result":"这里放入上传的json"}}
      401:
        description: token 认证不通过,可能是过期
      405:
        description: 请求方式错误
    :return:
    """
    raise Exception("认为改接口不在使用")
    lists = []
    ret_obj = ReturnInfo()
    jsons = request.json
    ids = jsons.get("ids")
    set_index = set()
    dicts = {}
    for items in ids:
        index = str(items["index"])
        lngid = items["lngid"]

        set_index.add(index)
        if index not in dicts.keys():
            dicts[index] = [lngid]
        else:
            dicts[index].append(lngid)

    rows = ""
    for index in set_index:
        try:
            base_obj_meta_a = "base_obj_meta_a_" + index
            # rows = mongo.db[base_obj_meta_a].find({"_id": {"$in": dicts[index]}})
            # for row in rows:
            #     jsondicts = json.loads(row["full_field"])
            #     lists.append(jsondicts)
        except Exception as e:
            ret_obj.msg_code = "FAILED"
            ret_obj.msg = "失败,可能是查询错误，或者查询的结果本生包含错误信息"
            ret_obj.data = {"result": rows, "errmsg": str(e)}
            return jsonify(ret_obj.todict())

    ret_obj.msg_code = "SUCCESS"
    ret_obj.msg = "成功"
    ret_obj.data = lists
    return jsonify(ret_obj.todict())
